#!/bin/sh

# Copyright(c) 2011 OpenDomo Services SL. Licensed under GPL v3 or later
# Isidro Catalan <icatalan@opendomo.com>

#KERNEL_VER=`uname -r`
#KERNEL_ARCH=`uname -m`
KERNEL_VER="2.6.27"
KERNEL_ARCH="i686"
INSMOD="/sbin/insmod"
#TODO: Change for the real path of the distro
#Udev needs full path
ENVIRONMENT="/usr/local/opendomo/koloader/"
# We store all downloaded modules here
LOCAL_REPOSITORY="$ENVIRONMENT/downloaded_modules"
REPOSITORY_FILE="$ENVIRONMENT/repositories.txt"
MODULES_INDEX="index.txt"
# TODO: Agree the modules url path
MODULES_FOLDER="repository/modules/$KERNEL_VER-$KERNEL_ARCH"
TMP_FILE="/tmp/zlndkw`date +%N`"
# Will store the device type plugged in
SUBSYSTEM=""

# Loads the module from the local or remote(s) repostories
loadModule ()
{
   success="0"
   MODULE_PATH="$1"
   MODULE_NAME=`basename $MODULE_PATH`

   while read REPOSITORY; do
      # URL accessed
      MODULE_URL="$REPOSITORY/$MODULES_FOLDER/$SUBSYSTEM/$MODULE_PATH.gz"
    	logger -t koloader -p info "Downloading $MODULE_NAME from $MODULE_URL"

      #Downloading the module
      wget -q $MODULE_URL -O "/tmp/$MODULE_NAME.gz"
      if [ "$?" != "0" ]; then
      	logger -t koloader -p warn "Error downloading $MODULE_NAME from $MODULE_URL"
         return -1
      fi

      #Decompress it
      gunzip -f "/tmp/$MODULE_NAME.gz" 2> /dev/null
      if [ "$?" != "0" ]; then
      	logger -t koloader -p warn "Error decompressing $MODULE_NAME"
         return -1
      fi

      # Install the module
      $INSMOD /tmp/$MODULE_NAME
      if [ "$?" = "0" ]; then
      	logger -t koloader -p info "Module $MODULE_NAME installed successfully"
      else
      	logger -t koloader -p warn "Error installing $MODULE_NAME"
         return -1
      fi

      # Store the module in the local repository

      # 1- Creates the scafolding
      actual=`pwd`
      cd $LOCAL_REPOSITORY
      for folder in `dirname $KERNEL_VER/$SUBSYSTEM/$MODULE_PATH | tr "/" "\n"`; do
         mkdir $folder 2> /dev/null
         cd $folder
      done
      cd $actual

      # 2 - Storing module
      mv -f "/tmp/$MODULE_NAME" "$LOCAL_REPOSITORY/$KERNEL_VER/$SUBSYSTEM/$MODULE_PATH"

      # 3 - Creating modprobe entry
      # TODO: load the module on each restart, decide where is the best place
      # to do it: rc.local?
      # TODO: remove the module after the device desconection
      return 0

   done < "$REPOSITORY_FILE"
}

# --------------------------- Main ---------------------------------------------

case "$1" in

   update)
      #DEV_CONNECTIONS="usb firewire pci"      
      DEV_CONNECTIONS="usb"
      
      echo "Updaing modules information..."
      # For each repository
      while read REPOSITORY; do
         error="0"
         echo "Contacting with [$REPOSITORY]"
         for CONN in `echo "$DEV_CONNECTIONS"`; do 

            # download index file
            wget -q $REPOSITORY/$MODULES_FOLDER/$CONN/$MODULES_INDEX -O $TMP_FILE

            if [ "$?" = "0" ] && [ -f $TMP_FILE ]; then
               if [ ! -d "$LOCAL_REPOSITORY" ]; then
                     mkdir "$LOCAL_REPOSITORY"
               fi
               if [ ! -d "$LOCAL_REPOSITORY/$CONN" ]; then
                     mkdir "$LOCAL_REPOSITORY/$CONN"
               fi
               mv $TMP_FILE $LOCAL_REPOSITORY/$CONN/$MODULES_INDEX
               #TODO: Add information about changes / updates
               echo "[$CONN] modules information successfully updated..."
              	logger -t koloader -p info "[$CONN] modules information successfully updated..."
            else
               echo "Error updating modules information, trying next connection / repository..."
            	logger -t koloader -p error "Error updating modules information, trying next connection / repository..."
               error="1"
               break;
            fi
         done

         # Check for errors while downloading
         if [ "$error" = "0" ]; then
            exit 0
         fi
      
      done < "$REPOSITORY_FILE"
   ;;
   
   inspect)
      echo "Looking for new devices... (not available yet)"
   ;;
   
   add) # Action called from udev

      # Environment vars from udev
      SUBSYSTEM=$2 #usb, firewire, etc...
      ID_VENDOR=$vendor
      ID_PRODUCT=$product
      INT_CLASS=$interface_class
      INT_SUBCLASS=$interface_subclass

      if [ -z "$ID_VENDOR" ]; then
         ID_VENDOR="0000"
      fi
      if [ -z "$ID_PRODUCT" ]; then
         ID_PRODUCT="0000"
      fi
      if [ -z "$INT_CLASS" ]; then
         INT_CLASS="00"
      fi
      if [ -z "$INT_SUBCLASS" ]; then
         INT_SUBCLASS="00"
      fi

      if [ "$ID_VENDOR" = "0000" ] && [ "$ID_PRODUCT" = "0000" ] && 
         [ "$INT_CLASS" = "00" ] && [ "$INT_SUBCLASS" = "00" ]; then
         # Filtering void requests just in case, avoiding possible configurations?
         echo "No params received, aborting..."
         exit 0
      fi    

      if [ -z "$KERNEL_VER" ]; then
         	logger -t koloader -p error "Wrong kernel version, exiting..."
         exit 1
      fi
      if [ -z "$SUBSYSTEM" ]; then
         	logger -t koloader -p error "No subsystem specified..."
         exit 1
      fi

      # We try to find the module with the information provided
      installed="0"
      for match in `grep "[0-9x]*$ID_VENDOR [0-9x]*$ID_PRODUCT [0x]*$INT_CLASS [0x]*$INT_SUBCLASS .*.ko" $LOCAL_REPOSITORY/$SUBSYSTEM/$MODULES_INDEX | sort | uniq`; do
         if echo "$match" | grep ".ko"; then
           	logger -t koloader -p info "Module found [$ID_VENDOR - $ID_PRODUCT - $INT_CLASS - $INT_SUBCLASS]"
            loadModule "$match"
            installed="1"
         fi
      done
      
      if [ "$installed" = "0" ]; then
        	logger -t koloader -p warn "Can not find any suitable module for this device with $ID_VENDOR - $ID_PRODUCT - $INT_CLASS - $INT_SUBCLASS received"
      fi

   ;;

esac

